home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095s.zip / NDISASM.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  7KB  |  270 lines

  1. /* ndisasm.c   the Netwide Disassembler main module
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #include "nasm.h"
  15. #include "nasmlib.h"
  16. #include "sync.h"
  17. #include "disasm.h"
  18.  
  19. #define BPL 8                   /* bytes per line of hex dump */
  20.  
  21. static const char *help =
  22. "usage: ndisasm [-a] [-i] [-h] [-r] [-u] [-b bits] [-o origin] [-s sync...]\n"
  23. "               [-e bytes] [-k start,bytes] file\n"
  24. "   -a or -i activates auto (intelligent) sync\n"
  25. "   -u sets USE32 (32-bit mode)\n"
  26. "   -b 16 or -b 32 sets number of bits too\n"
  27. "   -h displays this text\n"
  28. "   -r displays the version number\n"
  29. "   -e skips <bytes> bytes of header\n"
  30. "   -k avoids disassembling <bytes> bytes from position <start>\n";
  31.  
  32. static void output_ins (unsigned long, unsigned char *, int, char *);
  33. static void skip (unsigned long dist, FILE *fp);
  34.  
  35. int main(int argc, char **argv) {
  36.     unsigned char buffer[INSN_MAX * 2], *p, *q;
  37.     char outbuf[256];
  38.     char *pname = *argv;
  39.     char *filename = NULL;
  40.     unsigned long nextsync, synclen, initskip = 0L;
  41.     int lenread, lendis;
  42.     int autosync = FALSE;
  43.     int bits = 16;
  44.     int rn_error;
  45.     long offset;
  46.     FILE *fp;
  47.  
  48.     offset = 0;
  49.     init_sync();
  50.  
  51.     while (--argc) {
  52.     char *v, *vv, *p = *++argv;
  53.     if (*p == '-') {
  54.         p++;
  55.         while (*p) switch (tolower(*p)) {
  56.           case 'a':               /* auto or intelligent sync */
  57.           case 'i':
  58.         autosync = TRUE;
  59.         p++;
  60.         break;
  61.           case 'h':
  62.         fprintf(stderr, help);
  63.         return 0;
  64.           case 'r':
  65.         fprintf(stderr, "NDISASM version " NASM_VER "\n");
  66.         return 0;
  67.           case 'u':               /* USE32 */
  68.         bits = 32;
  69.         p++;
  70.         break;
  71.           case 'b':               /* bits */
  72.         v = p[1] ? p+1 : --argc ? *++argv : NULL;
  73.         if (!v) {
  74.             fprintf(stderr, "%s: `-b' requires an argument\n", pname);
  75.             return 1;
  76.         }
  77.         if (!strcmp(v, "16"))
  78.             bits = 16;
  79.         else if (!strcmp(v, "32"))
  80.             bits = 32;
  81.         else {
  82.             fprintf(stderr, "%s: argument to `-b' should"
  83.                 " be `16' or `32'\n", pname);
  84.         }
  85.         p = "";               /* force to next argument */
  86.         break;
  87.           case 'o':               /* origin */
  88.         v = p[1] ? p+1 : --argc ? *++argv : NULL;
  89.         if (!v) {
  90.             fprintf(stderr, "%s: `-o' requires an argument\n", pname);
  91.             return 1;
  92.         }
  93.         offset = readnum (v, &rn_error);
  94.         if (rn_error) {
  95.             fprintf(stderr, "%s: `-o' requires a numeric argument\n",
  96.                 pname);
  97.             return 1;
  98.         }
  99.         p = "";               /* force to next argument */
  100.         break;
  101.           case 's':               /* sync point */
  102.         v = p[1] ? p+1 : --argc ? *++argv : NULL;
  103.         if (!v) {
  104.             fprintf(stderr, "%s: `-s' requires an argument\n", pname);
  105.             return 1;
  106.         }
  107.         add_sync (readnum (v, &rn_error), 0L);
  108.         if (rn_error) {
  109.             fprintf(stderr, "%s: `-s' requires a numeric argument\n",
  110.                 pname);
  111.             return 1;
  112.         }
  113.         p = "";               /* force to next argument */
  114.         break;
  115.           case 'e':               /* skip a header */
  116.         v = p[1] ? p+1 : --argc ? *++argv : NULL;
  117.         if (!v) {
  118.             fprintf(stderr, "%s: `-e' requires an argument\n", pname);
  119.             return 1;
  120.         }
  121.         initskip = readnum (v, &rn_error);
  122.         if (rn_error) {
  123.             fprintf(stderr, "%s: `-e' requires a numeric argument\n",
  124.                 pname);
  125.             return 1;
  126.         }
  127.         p = "";               /* force to next argument */
  128.         break;
  129.           case 'k':               /* skip a region */
  130.         v = p[1] ? p+1 : --argc ? *++argv : NULL;
  131.         if (!v) {
  132.             fprintf(stderr, "%s: `-k' requires an argument\n", pname);
  133.             return 1;
  134.         }
  135.         vv = strchr(v, ',');
  136.         if (!vv) {
  137.             fprintf(stderr, "%s: `-k' requires two numbers separated"
  138.                 " by a comma\n", pname);
  139.             return 1;
  140.         }
  141.         *vv++ = '\0';
  142.         nextsync = readnum (v, &rn_error);
  143.         if (rn_error) {
  144.             fprintf(stderr, "%s: `-k' requires numeric arguments\n",
  145.                 pname);
  146.             return 1;
  147.         }
  148.         synclen = readnum (vv, &rn_error);
  149.         if (rn_error) {
  150.             fprintf(stderr, "%s: `-k' requires numeric arguments\n",
  151.                 pname);
  152.             return 1;
  153.         }
  154.         add_sync (nextsync, synclen);
  155.         p = "";               /* force to next argument */
  156.         break;
  157.         }
  158.     } else if (!filename) {
  159.         filename = p;
  160.     } else {
  161.         fprintf(stderr, "%s: more than one filename specified\n", pname);
  162.         return 1;
  163.     }
  164.     }
  165.  
  166.     if (!filename) {
  167.     fprintf(stderr, help, pname);
  168.     return 0;
  169.     }
  170.  
  171.     fp = fopen(filename, "rb");
  172.     if (initskip > 0)
  173.     skip (initskip, fp);
  174.  
  175.     /*
  176.      * This main loop is really horrible, and wants rewriting with
  177.      * an axe. It'll stay the way it is for a while though, until I
  178.      * find the energy...
  179.      */
  180.  
  181.     p = q = buffer;
  182.     nextsync = next_sync (offset, &synclen);
  183.     do {
  184.     unsigned long to_read = buffer+sizeof(buffer)-p;
  185.     if (to_read > nextsync-offset-(p-q))
  186.         to_read = nextsync-offset-(p-q);
  187.     lenread = fread (p, 1, to_read, fp);
  188.     p += lenread;
  189.     if (offset == nextsync) {
  190.         if (synclen) {
  191.         printf("%08lX  skipping 0x%lX bytes\n", offset, synclen);
  192.         offset += synclen;
  193.         skip (synclen, fp);
  194.         }
  195.         p = q = buffer;
  196.         nextsync = next_sync (offset, &synclen);
  197.     }
  198.     while (p > q && (p - q >= INSN_MAX || lenread == 0)) {
  199.         lendis = disasm (q, outbuf, bits, offset, autosync);
  200.         if (!lendis || lendis > (p - q) ||
  201.         lendis > nextsync-offset)
  202.         lendis = eatbyte (q, outbuf);
  203.         output_ins (offset, q, lendis, outbuf);
  204.         q += lendis;
  205.         offset += lendis;
  206.     }
  207.     if (q >= buffer+INSN_MAX) {
  208.         unsigned char *r = buffer, *s = q;
  209.         int count = p - q;
  210.         while (count--)
  211.         *r++ = *s++;
  212.         p -= (q - buffer);
  213.         q = buffer;
  214.     }
  215.     } while (lenread > 0 || !feof(fp));
  216.     fclose (fp);
  217.     return 0;
  218. }
  219.  
  220. static void output_ins (unsigned long offset, unsigned char *data,
  221.             int datalen, char *insn) {
  222.     int bytes;
  223.     printf("%08lX  ", offset);
  224.  
  225.     bytes = 0;
  226.     while (datalen > 0 && bytes < BPL) {
  227.     printf("%02X", *data++);
  228.     bytes++;
  229.     datalen--;
  230.     }
  231.  
  232.     printf("%*s%s\n", (BPL+1-bytes)*2, "", insn);
  233.  
  234.     while (datalen > 0) {
  235.     printf("         -");
  236.     bytes = 0;
  237.     while (datalen > 0 && bytes < BPL) {
  238.         printf("%02X", *data++);
  239.         bytes++;
  240.         datalen--;
  241.     }
  242.     printf("\n");
  243.     }
  244. }
  245.  
  246. /*
  247.  * Skip a certain amount of data in a file, either by seeking if
  248.  * possible, or if that fails then by reading and discarding.
  249.  */
  250. static void skip (unsigned long dist, FILE *fp) {
  251.     char buffer[256];               /* should fit on most stacks :-) */
  252.  
  253.     /*
  254.      * Got to be careful with fseek: at least one fseek I've tried
  255.      * doesn't approve of SEEK_CUR. So I'll use SEEK_SET and
  256.      * ftell... horrible but apparently necessary.
  257.      */
  258.     if (fseek (fp, dist+ftell(fp), SEEK_SET)) {
  259.     while (dist > 0) {
  260.         unsigned long len = (dist < sizeof(buffer) ?
  261.                  dist : sizeof(buffer));
  262.         if (fread (buffer, 1, len, fp) < len) {
  263.         perror("fread");
  264.         exit(1);
  265.         }
  266.         dist -= len;
  267.     }
  268.     }
  269. }
  270.